package com.dongdongshop.service.impl;

import com.alibaba.fastjson.JSON;
import com.dongdongshop.dto.ItemDTO;
import com.dongdongshop.page.PageParms;
import com.dongdongshop.page.PageUtil;
import com.dongdongshop.service.SearchService;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {
    //高级客户端
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    //默认的
    private final RequestOptions options = RequestOptions.DEFAULT;
    @Value("${restHighLevelClient.indices}")
    private String indices;
    //1.分页 2.条件查询  3.走分词器  4.增加扩展词典 5.高亮显示
    @Override
    public PageUtil getSearchByName(PageParms<String> parms) throws IOException {
        // 搜索请求对象
        SearchRequest searchRequest = new SearchRequest(indices);
        // 搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //分页
        int index = (parms.getPageNumber() - 1) * parms.getPageSize();
        searchSourceBuilder.from(index);
        searchSourceBuilder.size(parms.getPageSize());

        Map<String,Float> fields = new HashMap(3);
        fields.put("sell_point", 1.0f);
        fields.put("title", 1.0f);
        fields.put("category", 8.0f);
        //queryBuilder.must(QueryBuilders.multiMatchQuery(parms.getParms()).fields(fields));
        if (parms.getParms() != null && !parms.getParms().equals("")) {
            // Query-match单字段模糊查询
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(parms.getParms()).fields(fields));
            //searchSourceBuilder.query(QueryBuilders.matchQuery("category", parms.getParms()));
        } else {
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        }
        // 向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置高亮前缀
        highlightBuilder.preTags("<span style='color:red' >");
        //设置高亮字段
        highlightBuilder.field("title");
        highlightBuilder.field("sell_point");
        highlightBuilder.field("category");
        //设置高亮后缀
        highlightBuilder.postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        // 执行搜索,向ES发起http请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, options);
        // 搜索结果
        SearchHits hits = searchResponse.getHits();
        //总条数
        TotalHits totalHits = hits.getTotalHits();
        long value = totalHits.value;
        List<ItemDTO> list = new ArrayList<>();
        for (SearchHit hit : hits.getHits()) {
            // 源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String title = (String) sourceAsMap.get("title");//标题
            String sell_point = (String) sourceAsMap.get("sell_point");//描述
            String category = (String) sourceAsMap.get("category");//分类
            ItemDTO itemDTO = JSON.parseObject(JSON.toJSONString(sourceAsMap), ItemDTO.class);
            // 获取高亮查询的内容。如果存在，则替换原来的name
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields != null) {
                HighlightField nameField = highlightFields.get("title");
                if (nameField != null) {
                    Text[] fragments = nameField.getFragments();
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Text str : fragments) {
                        stringBuilder.append(str.string());
                    }
                    title = stringBuilder.toString();
                    itemDTO.setTitle(title);
                }
                HighlightField sellPoint = highlightFields.get("sell_point");
                if (sellPoint != null) {
                    Text[] fragments = sellPoint.getFragments();
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Text str : fragments) {
                        stringBuilder.append(str.string());
                    }
                    sell_point = stringBuilder.toString();
                    itemDTO.setSellPoint(sell_point);
                }
                HighlightField categoryFied = highlightFields.get("category");
                if (categoryFied != null) {
                    Text[] fragments = categoryFied.getFragments();
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Text str : fragments) {
                        stringBuilder.append(str.string());
                    }
                    category = stringBuilder.toString();
                    itemDTO.setCategory(category);
                }
            }
            list.add(itemDTO);
        }
        PageUtil pageUtil = new PageUtil();
        pageUtil.setTotal(value);
        pageUtil.setData(list);
        pageUtil.setPageNumber(parms.getPageNumber());
        pageUtil.setPageSize(parms.getPageSize());
        pageUtil.setTotalPage(pageUtil.getTotal() % pageUtil.getPageSize() == 0 ? pageUtil.getTotal() / pageUtil.getPageSize() : pageUtil.getTotal() / pageUtil.getPageSize() + 1);
        return pageUtil;
    }
}
